import { AxiosTransform, CreateAxiosOptions } from "./AxiosTransForm";
import { AxiosResponse } from "axios";
import { RequestOptions, Result } from "types/axios";
import { ContentTypeEnum, RequestEnum, ResultEnum } from "../enum/HttpEnum";
import { isObject, isString } from "lodash-es";
import { YAxios } from "./Axios";
import { useUserStore } from "@/store";
import { ElMessage } from "element-plus";
import router from "@/router";
import { downloadByData } from "@/utils/file/download";
import { GlobalSetting } from "@/utils/setting";
const transForm: AxiosTransform = {
  transFormRequestHook: (
    res: AxiosResponse<Result | BlobPart>,
    options: RequestOptions
  ) => {
    // 发生错误
    if (!res) {
      throw new Error("接口调用超时");
    }
    const { data } = res;
    const { errorMessageMode, downLoadFile } = options;
    if (!data) {
      ElMessage.error("接口请求错误，请稍后重试");
      throw new Error("接口调用超时");
    }

    const { code, message } = <Result>data;

    if (downLoadFile) {
      downloadByData(<BlobPart>data, downLoadFile);
      return data;
    }

    // code存在并且等于200
    const hasSuccess =
      data && Reflect.has(<Result>data, "code") && code === ResultEnum.SUCCESS;
    if (hasSuccess) {
      return data;
    }

    // 添加新的code判断时，需要throw new Error
    switch (code) {
      case ResultEnum.TIMEOUT:
        throw new Error("接口调用超时");
        break;
      // token不存在
      case ResultEnum.TOKEN:
        router.push("/error");
        throw new Error("token不存在");
        break;
      case ResultEnum.ERROR:
        router.push("/error_500");
        throw new Error("接口报错");
        break;
      default:
        if (errorMessageMode === "message") {
          ElMessage.error(message);
        }
        throw new Error("接口调用失败");
        break;
    }
  },

  // 请求之前处理config
  beforeRequestHook(config, options) {
    const { apiUrl, joinPrefix, urlPrefix } = options;

    if (joinPrefix) {
      config.url = `${urlPrefix}${config.url}`;
    }

    if (apiUrl && isString(apiUrl)) {
      config.url = `${apiUrl}${config.url}`;
    }

    if (options.downLoadFile) {
      config.responseType = "blob";
    }

    const params = config.params || {};
    const data = config.data || false;
    if (config.method?.toUpperCase() === RequestEnum.GET) {
      if (!isString(params)) {
        // 给 get 请求加上时间戳参数，避免从缓存中拿数据。
      } else {
        config.params = undefined;
      }
    } else {
      if (!isString(params)) {
        if (
          Reflect.has(config, "data") &&
          config.data &&
          Object.keys(config.data).length > 0
        ) {
          config.data = data;
          config.params = params;
        } else if (config.data instanceof FormData) {
          config.data.append("version", params.version);
        } else {
          // 非GET请求如果没有提供data，则将params视为data
          config.data = params;
          config.params = undefined;
        }
      } else {
        config.url = config.url + params;
        config.params = undefined;
      }
    }
    return config;
  },

  // 请求拦截器处理
  requestInterceptors: (config, options) => {
    const userStore = useUserStore();
    const token = userStore.token;
    if (token && options.requestOptions?.withToken) {
      if (config.headers) {
        config.headers["Authorization"] = token;
      }
    }
    return config;
  },

  // 响应拦截器处理
  responseInterceptors: (res: AxiosResponse<any>) => {
    return res;
  },

  // 响应错误处理
  responseInterceptorsCatch: (error: any) => {
    return Promise.reject(error);
  },
};

function createAxios(opt?: Partial<CreateAxiosOptions>) {
  return new YAxios(
    deepMerge(
      {
        timeout: 10 * 1000,
        // 基础接口地址
        baseURL: GlobalSetting.VITE_BASE_URL,
        headers: { "Content-Type": ContentTypeEnum.JSON },
        // 如果是form-data格式
        // headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED },
        // 数据处理方式
        transForm,
        // 配置项，下面的选项都可以在独立的接口请求中覆盖
        requestOptions: {
          // 消息提示类型
          errorMessageMode: "message",
          // 携带token
          withToken: true,
          // 下载文件,
          downloadFile: false,
          // 接口地址
          apiUrl: "",
          // 忽略重复请求
          ignoreCancelToken: true,
          // loading  yes/no
          loading: true,
        },
      },
      opt || {}
    )
  );
}

function deepMerge<T = any>(src: any = {}, target: any = {}): T {
  let key: string;
  for (key in target) {
    src[key] = isObject(src[key])
      ? deepMerge(src[key], target[key])
      : (src[key] = target[key]);
  }
  return src;
}

export const Http = createAxios({
  baseURL: GlobalSetting.VITE_GLOB_API_URL,
});

export const MockHttp = createAxios({
  baseURL: GlobalSetting.VITE_BASE_URL,
});
